package com.ruoyi.article.controller;


import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.ruoyi.article.entity.ArticleVo;
import com.ruoyi.article.entity.GMapNetCache;
import com.ruoyi.article.service.ArticleService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * @author hlf
 * @createTime 2025/2/11 10:32
 * @description
 */
@RestController
@RequestMapping("/article")
public class ArticleController extends BaseController {

    @Autowired
    private ArticleService articleService;

    /**
     * @description 数据库新增，发消息队列，同步es
     * @author hlf
     * @date 2025/2/11 9:43
     **/
    @PostMapping("/add")
    @Anonymous
    public AjaxResult add(@RequestBody ArticleVo article) {
        articleService.add(article);
        return AjaxResult.success();
    }


    /**
     * @description 数据库修改，发消息队列，同步es
     * @author hlf
     * @date 2025/2/11 9:43
     **/
    @PostMapping("/updateArticle")
    @Anonymous
    public AjaxResult  updateArticle(@RequestBody ArticleVo article) {
        articleService.updateArticle(article);
        return AjaxResult.success();
    }

    /**
     * @description 数据库删除，发消息队列，同步es
     * @author hlf
     * @date 2025/2/11 9:43
     **/
    @PostMapping("/deleteArticle")
    @Anonymous
    public AjaxResult  deleteArticle(@RequestBody ArticleVo article) {
        articleService.deleteArticle(article);
        return AjaxResult.success();
    }


    /**
     * @description 全部数据查询 ，发消息队列，同步es
     * @author hlf
     * @date 2025/2/11 9:43
     **/
    @PostMapping("/addAll")
    @Anonymous
    public AjaxResult addAll(@RequestBody ArticleVo article) {
        articleService.addAll(article);
        return AjaxResult.success();
    }


    /**
     * @description CompletableFuture 使用
     * @author hlf
     * @date 2025/2/11 9:43
     **/
    @PostMapping("/async/testExample")
    @Anonymous
    public void asyncTestExample(@RequestBody ArticleVo article) {
        CompletableFuture<Integer> future = articleService.asyncTestExample(article);
        future.whenComplete((result, throwable) -> {
            if (throwable != null) {
                System.err.println("异步任务执行失败: " + throwable.getMessage());
            } else {
                System.out.println("异步任务执行成功，结果为: " + result);
            }
        });
    }

    /**
     * @param article
     * @return java.lang.String
     * @description 测试使用分布式锁 手动实现
     * @author hlf
     * @date 2025/2/17 15:30
     **/
    @PostMapping("/article/updateArticlePriceTest")
    @Anonymous
    public void updateArticlePriceTest(@RequestBody ArticleVo article) {
         articleService.updateArticlePriceTest(article);
    }


    /**
     * @param article
     * @return java.lang.String
     * @description 测试使用分布式锁 redission
     * @author hlf
     * @date 2025/2/17 15:30
     **/
    @PostMapping("/article/updateArticlePriceTest2")
    @Anonymous
    public void updateArticlePriceTest2(@RequestBody ArticleVo article) {
        articleService.updateArticlePriceTest2(article);
    }



    /**
     * @description 测试qps
     * @author hlf
     * @date 2025/2/19 8:38
     **/
    @PostMapping("/article/qpsTest")
    @Anonymous
    @RepeatSubmit
    public TableDataInfo qpsTest(@RequestBody ArticleVo article) {
        startPage();
        List<ArticleVo> list = articleService.qpsTest(article);
        return getDataTable(list);
    }


    /**
     * @description  使用分布式锁 模拟扣减库存
     * @author hlf
     * @date 2025/2/19 8:38
     **/
    @PostMapping("/article/cutPrice")
    @Anonymous
    @SentinelResource(value = "/article/article/cutPrice", blockHandler = "handleBlock")
    public AjaxResult cutPrice(@RequestBody ArticleVo article) {
        articleService.cutPrice(article);
       return AjaxResult.success();
    }

    /**
     * @description 对应上方方法限流后的输出方法
     * @author hlf
     * @date 2025/2/20 16:08
     * @param article
     * @param ex
     * @return com.ruoyi.common.core.domain.AjaxResult
     **/
    public AjaxResult handleBlock(ArticleVo article,BlockException ex) {
        System.out.println("Sentinel 流控触发，进入 handleBlock 方法！");
        return AjaxResult.error("请求被限流，请稍后重试");
    }

    @GetMapping(value = "/tiles/{type}/{zoom}/{x}/{y}.png", produces = MediaType.IMAGE_PNG_VALUE)
    @Anonymous
    public void getTile(
            @PathVariable int type,
            @PathVariable int zoom,
            @PathVariable int x,
            @PathVariable int y,
            HttpServletResponse response) throws IOException {
        GMapNetCache tile = articleService.findByTypeAndZoomAndXAndY(type, zoom, x, y);
        if (tile != null && tile.getTile() != null) {
            response.setContentType("image/png");  // 设置响应类型
            response.getOutputStream().write(tile.getTile()); // 输出瓦片数据
            response.getOutputStream().flush();
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "Tile not found");
        }
    }


}
